package com.apisix.service.service;

import com.apisix.service.entity.Upstream;
import com.apisix.service.repository.UpstreamRepository;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Service
public class UpstreamService {

    private final UpstreamRepository upstreamRepository;
    private final ApisixService apisixService;
    private final ObjectMapper objectMapper;

    @Autowired
    public UpstreamService(UpstreamRepository upstreamRepository, ApisixService apisixService, ObjectMapper objectMapper) {
        this.upstreamRepository = upstreamRepository;
        this.apisixService = apisixService;
        this.objectMapper = objectMapper;
    }

    public List<Upstream> getAllUpstreams() {
        return upstreamRepository.findAll();
    }

    public Optional<Upstream> getUpstreamById(Long id) {
        return upstreamRepository.findById(id);
    }

    public Optional<Upstream> getUpstreamByUpstreamId(String upstreamId) {
        return upstreamRepository.findByUpstreamId(upstreamId);
    }

    @Transactional
    public Upstream createUpstream(Upstream upstream) throws JsonProcessingException {
        // 如果未提供上游ID，则生成一个UUID
        if (upstream.getUpstreamId() == null || upstream.getUpstreamId().isEmpty()) {
            upstream.setUpstreamId(UUID.randomUUID().toString());
        }
        
        // 保存到数据库
        Upstream savedUpstream = upstreamRepository.save(upstream);
        
        // 在APISIX中创建
        Map<String, Object> upstreamData = convertToApisixFormat(savedUpstream);
        apisixService.createUpstream(upstreamData);
        
        return savedUpstream;
    }

    @Transactional
    public Optional<Upstream> updateUpstream(Long id, Upstream upstreamDetails) throws JsonProcessingException {
        return upstreamRepository.findById(id)
                .map(existingUpstream -> {
                    // 更新上游信息
                    existingUpstream.setName(upstreamDetails.getName());
                    existingUpstream.setType(upstreamDetails.getType());
                    existingUpstream.setNodes(upstreamDetails.getNodes());
                    existingUpstream.setTimeout(upstreamDetails.getTimeout());
                    existingUpstream.setRetries(upstreamDetails.getRetries());
                    existingUpstream.setScheme(upstreamDetails.getScheme());
                    existingUpstream.setPassHost(upstreamDetails.getPassHost());
                    existingUpstream.setHashOn(upstreamDetails.getHashOn());
                    existingUpstream.setKey(upstreamDetails.getKey());
                    existingUpstream.setChecks(upstreamDetails.getChecks());
                    existingUpstream.setDescription(upstreamDetails.getDescription());
                    
                    Upstream updatedUpstream = upstreamRepository.save(existingUpstream);
                    
                    try {
                        // 在APISIX中更新
                        Map<String, Object> upstreamData = convertToApisixFormat(updatedUpstream);
                        apisixService.updateUpstream(updatedUpstream.getUpstreamId(), upstreamData);
                    } catch (JsonProcessingException e) {
                        throw new RuntimeException("Failed to update upstream in APISIX", e);
                    }
                    
                    return updatedUpstream;
                });
    }

    @Transactional
    public boolean deleteUpstream(Long id) {
        return upstreamRepository.findById(id)
                .map(upstream -> {
                    // 首先从APISIX中删除
                    apisixService.deleteUpstream(upstream.getUpstreamId());
                    
                    // 然后从数据库中删除
                    upstreamRepository.delete(upstream);
                    return true;
                })
                .orElse(false);
    }

    public boolean existsByUpstreamId(String upstreamId) {
        return upstreamRepository.existsByUpstreamId(upstreamId);
    }
    
    @Transactional
    public void syncUpstreamsFromApisix() {
        List<Map<String, Object>> apisixUpstreams = apisixService.getUpstreams();
        
        for (Map<String, Object> apisixUpstream : apisixUpstreams) {
            String upstreamId = (String) apisixUpstream.get("id");
            
            if (!upstreamRepository.existsByUpstreamId(upstreamId)) {
                Upstream upstream = new Upstream();
                upstream.setUpstreamId(upstreamId);
                
                // 提取上游信息
                Map<String, Object> value = (Map<String, Object>) apisixUpstream.get("value");
                
                if (value.containsKey("name")) {
                    upstream.setName((String) value.get("name"));
                }
                
                if (value.containsKey("type")) {
                    upstream.setType((String) value.get("type"));
                }
                
                if (value.containsKey("nodes")) {
                    try {
                        upstream.setNodes(objectMapper.writeValueAsString(value.get("nodes")));
                    } catch (JsonProcessingException e) {
                        // 忽略转换错误
                    }
                }
                
                if (value.containsKey("timeout")) {
                    Map<String, Object> timeout = (Map<String, Object>) value.get("timeout");
                    upstream.setTimeout((Integer) timeout.get("connect"));
                }
                
                if (value.containsKey("retries")) {
                    upstream.setRetries((Integer) value.get("retries"));
                }
                
                if (value.containsKey("scheme")) {
                    upstream.setScheme((String) value.get("scheme"));
                }
                
                if (value.containsKey("pass_host")) {
                    upstream.setPassHost((String) value.get("pass_host"));
                }
                
                if (value.containsKey("hash_on")) {
                    upstream.setHashOn((String) value.get("hash_on"));
                }
                
                if (value.containsKey("key")) {
                    upstream.setKey((String) value.get("key"));
                }
                
                if (value.containsKey("checks")) {
                    try {
                        upstream.setChecks(objectMapper.writeValueAsString(value.get("checks")));
                    } catch (JsonProcessingException e) {
                        // 忽略转换错误
                    }
                }
                
                if (value.containsKey("desc")) {
                    upstream.setDescription((String) value.get("desc"));
                }
                
                upstreamRepository.save(upstream);
            }
        }
    }
    
    private Map<String, Object> convertToApisixFormat(Upstream upstream) throws JsonProcessingException {
        Map<String, Object> upstreamData = new HashMap<>();
        
        upstreamData.put("id", upstream.getUpstreamId());
        
        if (upstream.getName() != null && !upstream.getName().isEmpty()) {
            upstreamData.put("name", upstream.getName());
        }
        
        if (upstream.getType() != null && !upstream.getType().isEmpty()) {
            upstreamData.put("type", upstream.getType());
        }
        
        if (upstream.getNodes() != null && !upstream.getNodes().isEmpty()) {
            Object nodes = objectMapper.readValue(upstream.getNodes(), Object.class);
            upstreamData.put("nodes", nodes);
        }
        
        if (upstream.getTimeout() != null) {
            Map<String, Object> timeout = new HashMap<>();
            timeout.put("connect", upstream.getTimeout());
            timeout.put("send", upstream.getTimeout());
            timeout.put("read", upstream.getTimeout());
            upstreamData.put("timeout", timeout);
        }
        
        if (upstream.getRetries() != null) {
            upstreamData.put("retries", upstream.getRetries());
        }
        
        if (upstream.getScheme() != null && !upstream.getScheme().isEmpty()) {
            upstreamData.put("scheme", upstream.getScheme());
        }
        
        if (upstream.getPassHost() != null && !upstream.getPassHost().isEmpty()) {
            upstreamData.put("pass_host", upstream.getPassHost());
        }
        
        if (upstream.getHashOn() != null && !upstream.getHashOn().isEmpty()) {
            upstreamData.put("hash_on", upstream.getHashOn());
        }
        
        if (upstream.getKey() != null && !upstream.getKey().isEmpty()) {
            upstreamData.put("key", upstream.getKey());
        }
        
        if (upstream.getChecks() != null && !upstream.getChecks().isEmpty()) {
            Map<String, Object> checks = objectMapper.readValue(upstream.getChecks(), Map.class);
            upstreamData.put("checks", checks);
        }
        
        if (upstream.getDescription() != null && !upstream.getDescription().isEmpty()) {
            upstreamData.put("desc", upstream.getDescription());
        }
        
        return upstreamData;
    }
} 